package com.ag.improvedjava.iterable;

import java.util.Iterator;

import com.ag.improvedjava.utils.Function2;

final class ZipIterable<T, U, R> implements Iterable<R> {

	private Iterable<T> firstIterable;
	private Iterable<U> secondIterable;
	private Function2<T, U, R> resultSelector;
	
	ZipIterable(Iterable<T> firstIterable, Iterable<U> secondIterable, Function2<T, U, R> resultSelector) {
		this.firstIterable = firstIterable;
		this.secondIterable = secondIterable;
		this.resultSelector = resultSelector;
	}

	@Override
	public Iterator<R> iterator() {
		return new ZipIterator<>(firstIterable.iterator(), secondIterable.iterator(), resultSelector);
	}
}

class ZipIterator<T, U, R> extends UnmodifiableIterator<R> {
	
	private Iterator<T> firstIterator;
	private Iterator<U> secondIterator;
	private Function2<T, U, R> resultSelector;
	
	ZipIterator(Iterator<T> firstIterator, Iterator<U> secondIterator, Function2<T, U, R> resultSelector) {
		this.firstIterator = firstIterator;
		this.secondIterator = secondIterator;
		this.resultSelector = resultSelector;
	}

	@Override
	public boolean hasNext() {
		return firstIterator.hasNext() && secondIterator.hasNext();
	}

	@Override
	public R next() {
		return resultSelector.execute(firstIterator.next(), secondIterator.next());
	}

}
